use crate::todo::{Todo, TodoRequest};
use actix_web::{delete, get, post, put, web, HttpResponse, HttpRequest,Responder};
use sqlx::SqlitePool;
use log::info;
use serde_derive::Deserialize;
#[get("/rest/Todo/")]
async fn find_all(db_pool: web::Data<SqlitePool>) -> impl Responder {
    let result = Todo::find_all(db_pool.get_ref()).await;
    match result {
        Ok(todos) => HttpResponse::Ok().json(todos),
        _ => HttpResponse::BadRequest()
            .body("Error trying to read all todos from database"),
    }
}
// url 解析
#[derive(Deserialize)]
pub struct SqlRequest {
   cmd: String,
}

#[get("/rest/sql/")]
async fn rest_sql(web::Query(info1): web::Query<SqlRequest>,db_pool: web::Data<SqlitePool>) -> impl Responder {
    // info!("{}",req.match_info());
    // info!("REQ: {:?}", req);
    // info!("{}",info1.cmd);
    // let r = req.match_info().get("cmd");
    // match r {
    //     None =>HttpResponse::Ok().json(info.cmd),
    //     Some(cmd)=> HttpResponse::Ok().json(1),
    // }   
    // HttpResponse::Ok().json("hello")
    // info!("{}",cmd);
    let result = Todo::sql(info1.cmd,db_pool.get_ref()).await;
    match result {
        Ok(todos) => HttpResponse::Ok().json(todos),
        _ => HttpResponse::BadRequest()
            .body("Error trying to read all todos from database"),
    }
}


#[get("/todo/{id}")]
async fn find(id: web::Path<i32>, db_pool: web::Data<SqlitePool>) -> impl Responder {
    let result = Todo::find_by_id(id.into_inner(), db_pool.get_ref()).await;
    match result {
        Ok(todo) => HttpResponse::Ok().json(todo),
        _ => HttpResponse::BadRequest().body("Todo not found"),
    }
}

#[post("/rest/Todo/")]
async fn create(
    todo: web::Json<TodoRequest>,
    db_pool: web::Data<SqlitePool>,
) -> impl Responder {
    info!("create");
    let result = Todo::create(todo.into_inner(), db_pool.get_ref()).await;
    match result {
        Ok(todo) => HttpResponse::Ok().json(todo),
        Err(v)=> {
            info!("{}",v);
            return HttpResponse::BadRequest().body("Error trying to create new todo");
        },
    }
}

#[put("/rest/Todo/")]
async fn update(
    todo: web::Json<Todo>,
    db_pool: web::Data<SqlitePool>,
) -> impl Responder {
    info!("{}",todo.id);
    // HttpResponse::Ok().json("update")
    let result =
        Todo::update(todo.into_inner(), db_pool.get_ref()).await;
    match result {
        Ok(todo) => HttpResponse::Ok().json(todo),
        _ => HttpResponse::BadRequest().body("Todo not found"),
    }
}

#[delete("/todo/{id}")]
async fn delete(id: web::Path<i32>, db_pool: web::Data<SqlitePool>) -> impl Responder {
    let result = Todo::delete(id.into_inner(), db_pool.get_ref()).await;
    match result {
        Ok(rows) => {
            if rows > 0 {
                HttpResponse::Ok()
                    .body(format!("Successfully deleted {} record(s)", rows))
            } else {
                HttpResponse::BadRequest().body("Todo not found")
            }
        }
        _ => HttpResponse::BadRequest().body("Todo not found"),
    }
}

// function that will be called on new Application to configure routes for this module
pub fn init(cfg: &mut web::ServiceConfig) {
    cfg.service(find_all);
    cfg.service(find);
    cfg.service(create);
    cfg.service(update);
    cfg.service(delete);
    cfg.service(rest_sql);
    info!("after init");
}
